from typing import Callable
import inspect
from .logger import get_default_logger


def middleware(func: Callable) -> Callable:
    """简单中间件装饰器 - 15行解决所有中间件需求"""
    setattr(func, "is_middleware", True)
    return func


# 内置中间件示例
@middleware
def cors_middleware(handler: Callable):
    """CORS中间件"""

    async def wrapper(*args, **kwargs):
        # 简化的CORS逻辑
        result = await handler(*args, **kwargs)
        if hasattr(result, "headers"):
            result.headers.setdefault("Access-Control-Allow-Origin", "*")
        return result

    return wrapper


@middleware
def logging_middleware(handler: Callable):
    """日志中间件"""

    async def wrapper(scope, receive, send, *args, **kwargs):
        logger = get_default_logger()
        logger.info(
            "请求经过日志中间件",
            event="middleware_request_received",
            method=scope.get('method', 'WS'),
            path=scope['path'],
            client_ip=scope.get('client', ['unknown'])[0] if scope.get('client') else 'unknown'
        )
        return await handler(scope, receive, send, *args, **kwargs)

    return wrapper


# 流式处理中间件
@middleware
def streaming_middleware(handler: Callable):
    """流式请求中间件 - 自动检测和处理流式请求"""
    
    async def wrapper(scope, receive, send, *args, **kwargs):
        # 检查是否为流式请求
        if scope.get("method") in ["POST", "PUT", "PATCH"]:
            headers = dict(scope.get("headers", []))
            content_length = headers.get(b"content-length", b"0").decode()
            transfer_encoding = headers.get(b"transfer-encoding", b"").decode().lower()
            
            is_large = int(content_length) > 1024 * 1024  # 1MB
            is_chunked = "chunked" in transfer_encoding
            
            if is_large or is_chunked:
                # 创建流式请求对象
                from .core import Request
                request = Request(scope, receive)
                
                # 添加到参数中
                if "request" in kwargs:
                    kwargs["request"] = request
                else:
                    # 自动注入request参数
                    sig = inspect.signature(handler)
                    if "request" in sig.parameters:
                        kwargs["request"] = request
                        
        return await handler(scope, receive, send, *args, **kwargs)
        
    return wrapper


# 自动应用流式中间件的装饰器
def auto_stream(func):
    """自动应用流式支持的装饰器"""
    # 创建一个包装器函数，保持原始函数的签名
    async def wrapper(*args, **kwargs):
        # 如果第一个参数是request对象，直接传递
        if args and hasattr(args[0], 'stream_body'):
            return await func(*args, **kwargs)
        # 否则，尝试从kwargs中提取request
        elif 'request' in kwargs:
            return await func(kwargs['request'])
        # 如果都没有，尝试直接调用原始函数
        else:
            return await func(*args, **kwargs)
    
    # 保持原始函数的元数据
    import functools
    wrapper = functools.update_wrapper(wrapper, func)
    return wrapper


# SSE中间件
@middleware
def sse_middleware(handler: Callable):
    """SSE中间件 - 自动处理SSE连接"""
    
    async def wrapper(scope, receive, send, *args, **kwargs):
        # 检查是否为SSE请求
        headers = dict(scope.get("headers", []))
        accept = headers.get(b"accept", b"").decode()
        
        if "text/event-stream" in accept:
            # SSE请求特殊处理
            from .streaming import sse_manager
            
            # 创建包装的send函数来管理连接
            original_send = send
            sse_mgr = getattr(handler, 'sse_manager', sse_manager)
            
            async def sse_send(message):
                await original_send(message)
                
            # 添加到连接管理
            if sse_mgr:
                sse_mgr.add(sse_send)
                
            try:
                result = await handler(scope, receive, sse_send, *args, **kwargs)
                
                # 如果返回的是SSE响应，自动管理连接
                if hasattr(result, 'content_generator'):
                    sse_mgr.add(sse_send)
                    
                return result
            except Exception as e:
                if sse_mgr:
                    sse_mgr.remove(sse_send)
                raise
        else:
            return await handler(scope, receive, send, *args, **kwargs)
            
    return wrapper
